package com.iplant.base.utils.remote;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import com.alibaba.fastjson.JSON;
import com.iplant.base.po.APIResult;
import com.iplant.base.utils.general.StringUtils;

@Component
public class RemoteInvokeUtils {
	private static Logger logger = LoggerFactory.getLogger(RemoteInvokeUtils.class);

	@Autowired
	RestTemplate restTemplate;

	public RemoteInvokeUtils() {

	}

	@PostConstruct
	public void init() {
		Instance = this;
		Instance.restTemplate = this.restTemplate;
		
	}

	private static RemoteInvokeUtils Instance = null;

	public static RemoteInvokeUtils getInstance() {
		if (Instance == null)
			Instance = new RemoteInvokeUtils();

		return Instance;
	}

	public String HttpInvokeString(String wUrl, Map<String, Object> wParams, HttpMethod wHttpMethod) {
		String wResult = "";
		try {
			// 拼接url
			wResult = HttpInvoke(wUrl, wParams, wHttpMethod, String.class);
		} catch (Exception e) {
			logger.error(e.toString());
		}
		return wResult;

	}

	private String HandleUrl(String wServerUrl, String wUrl) {
		if (wServerUrl == null || wServerUrl.length() < 1) {
			return wUrl;
		}
		if (wUrl == null || wUrl.length() < 1)
			return "";

		if (wServerUrl.endsWith("/")) {
			if (wUrl.startsWith("/")) {
				return StringUtils.Format("{0}{1}", wServerUrl, wUrl.substring(1));
			} else {
				return StringUtils.Format("{0}{1}", wServerUrl, wUrl);
			}
		} else {
			if (wUrl.startsWith("/")) {

				return StringUtils.Format("{0}{1}", wServerUrl, wUrl);
			} else {
				return StringUtils.Format("{0}/{1}", wServerUrl, wUrl);
			}
		}

	}

	public String HttpInvokeString(String wServerUrl, String wUrl, Map<String, Object> wParams, HttpMethod wHttpMethod) {
		String wResult = "";
		try {
			if (StringUtils.isEmpty(wServerUrl))
				wServerUrl = "";
			// 拼接url
			wResult = HttpInvoke(HandleUrl(wServerUrl, wUrl), wParams, wHttpMethod, String.class);
		} catch (Exception e) {
			logger.error(e.toString());
		}
		return wResult;

	}

	public <T> T HttpInvoke(String wServerUrl, String wUrl, Map<String, Object> wParams, HttpMethod wHttpMethod,
			Class<T> clazz) {
		T wResult = null;
		try {
			if (StringUtils.isEmpty(wServerUrl))
				wServerUrl = "";
			wResult = clazz.newInstance();
			wResult = HttpInvoke(HandleUrl(wServerUrl, wUrl), wParams, wHttpMethod, clazz);
		} catch (Exception e) {
			logger.error(e.toString());
		}
		return wResult;
	}

	public <T> T HttpInvoke(String wUrl, Map<String, Object> wParams, HttpMethod wHttpMethod, Class<T> clazz) {
		T wResult = null;
		try {
			wResult = clazz.newInstance();
			if (wParams == null)
				wParams = new HashMap<String, Object>();
			// 拼接url

			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
			HttpEntity<String> entity = new HttpEntity<String>(StringUtils.toJSONString(wParams), headers);
			ResponseEntity<T> wResponseEntity = new ResponseEntity<T>(HttpStatus.OK);
			switch (wHttpMethod) {
			case DELETE:
				break;
			case HEAD:
				break;
			case OPTIONS:
				break;
			case PATCH:
				break;
			case PUT:
				break;
			case TRACE:
				break;
			case GET:

				String wParmsString = "";
				for (String wKey : wParams.keySet()) {
					if (wParams.get(wKey) == null)
						continue;
					if (wParams.get(wKey) instanceof Calendar) {
						wParmsString += StringUtils.Format("{0}={1}&", wKey,
								StringUtils.parseCalendarToString((Calendar) wParams.get(wKey), "yyyy-MM-dd HH:mm:ss"));
					} else {
						wParmsString += StringUtils.Format("{0}={1}&", wKey, wParams.get(wKey));
					} 
				}

				if (wUrl.indexOf('?') > 5) {
					wUrl = StringUtils.Format("{0}{1}{2}", wUrl.substring(0, wUrl.indexOf('?') + 1), wParmsString,
							wUrl.substring(wUrl.indexOf('?') + 1));
				} else {
					wUrl = StringUtils.Format("{0}?{1}aipd={2}", wUrl, wParmsString, Math.random());
				}

				wResponseEntity = restTemplate.getForEntity(wUrl, clazz);

				break;
			case POST:
				if (wParams.containsKey("Form_Urlencoded")
						&& StringUtils.parseInt(wParams.containsKey("Form_Urlencoded")) > 0) {
					wParams.remove("Form_Urlencoded");
					headers.clear();
					headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
					MultiValueMap<String, Object> wParamS = new LinkedMultiValueMap<>();
					for (String String : wParams.keySet()) {
						wParamS.add(String, wParams.get(String));
					}
					HttpEntity<MultiValueMap<String, Object>> entityA = new HttpEntity<MultiValueMap<String, Object>>(
							wParamS, headers);
					wResponseEntity = restTemplate.exchange(wUrl, wHttpMethod, entityA, clazz);

				} else {
					wResponseEntity = restTemplate.exchange(wUrl, wHttpMethod, entity, clazz);
				}
				break;
			default:
				break;
			}

			wResult = wResponseEntity.getBody();
		} catch (Exception e) {
			logger.error("url:" + wUrl + "  error:" , e);
		}
		return wResult;
	}

	public APIResult HttpInvokeAPI(String wUrl, Map<String, Object> wParams, HttpMethod wHttpMethod) {
		APIResult wResult = new APIResult();
		try {
			wResult = HttpInvoke(wUrl, wParams, wHttpMethod, APIResult.class);

		} catch (Exception e) {
			logger.error(e.toString());
		}
		return wResult;
	}

	/**
	 * 
	 * @param wServerUrl   http://IP:端口/
	 * @param wProjectName 项目名称
	 * @param wUrl
	 * @param wParams
	 * @param wHttpMethod
	 * @return
	 */
	public APIResult HttpInvokeAPI(String wServerUrl, String wProjectName, String wUrl, Map<String, Object> wParams,
			HttpMethod wHttpMethod) {

		if (StringUtils.isEmpty(wProjectName))
			wProjectName = "";
		if (wUrl != null && wUrl.startsWith("/"))
			wUrl = wUrl.substring(1);
		return HttpInvokeAPI(wServerUrl, StringUtils.Format("{0}/{1}", wProjectName, wUrl), wParams, wHttpMethod);
	}

	/**
	 * 
	 * @param wServerUrl   http://IP:端口/
	 * @param wProjectName 项目名称
	 * @param wUrl
	 * @param wParams
	 * @param wHttpMethod
	 * @return
	 */
	public <T> T HttpInvokeAPI(String wServerUrl, String wProjectName, String wUrl, Map<String, Object> wParams,
			HttpMethod wHttpMethod, Class<T> clazz) {

		if (StringUtils.isEmpty(wProjectName))
			wProjectName = "";
		if (wUrl != null && wUrl.startsWith("/"))
			wUrl = wUrl.substring(1);
		return HttpInvokeAPI(wServerUrl, StringUtils.Format("{0}/{1}", wProjectName, wUrl), wParams, wHttpMethod, clazz);
	}

	public APIResult HttpInvokeAPI(String wServerUrl, String wUrl, Map<String, Object> wParams, HttpMethod wHttpMethod) {
		APIResult wResult = new APIResult();
		try {
			if (StringUtils.isEmpty(wServerUrl))
				wServerUrl = "";
			wResult = HttpInvoke(HandleUrl(wServerUrl, wUrl), wParams, wHttpMethod, APIResult.class);
		} catch (Exception e) {
			logger.error(e.toString());
		}
		return wResult;
	}

	public <T> T HttpInvokeAPI(String wServerUrl, String wUrl, Map<String, Object> wParams, HttpMethod wHttpMethod,
			Class<T> clazz) {
		T wResult = null;
		try {
			if (StringUtils.isEmpty(wServerUrl))
				wServerUrl = "";
			wResult = HttpInvoke(HandleUrl(wServerUrl, wUrl), wParams, wHttpMethod, clazz);
		} catch (Exception e) {
			logger.error(e.toString());
		}
		return wResult;
	}
 
}
